package com.biz.aoao.mysql.mysqlbinlogsync.config;

import com.alibaba.fastjson.PropertyNamingStrategy;
import com.alibaba.fastjson.parser.ParserConfig;
import com.alibaba.fastjson.util.TypeUtils;
import com.biz.aoao.mysql.mysqlbinlogsync.listener.IMysqlDataListener;
import lombok.Data;

import java.io.Serializable;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;


@Data
public class TalbeConfigInfo<T> {

    private String database;

    private String tableName;

    private Class<T>  entityClass;

    /*对应的数据处理类*/
    private IMysqlDataListener<T> listener;

    /*表字段*/
    private String[] columns;

    /*服务名*/
    private Long  serverid;


    private static final ParserConfig snakeCase=new ParserConfig();

    static {
        snakeCase.propertyNamingStrategy = PropertyNamingStrategy.SnakeCase;
    }
    /**
     * 数组转对象
     * @param data
     * @return
     */
    private T toEntity(Serializable[] data) {
        for (int i = 0; i < data.length; i++) {
            Serializable da = data[i];
            if (da instanceof Date) {
                data[i] = new Date(((Date)da).getTime());
            }
        }
        Map<String, Object> b = new HashMap<>(data.length);
        for (int i = 0; i < data.length; i++) {
            b.put(columns[i], data[i]);
        }
        return TypeUtils.cast(b, entityClass, snakeCase);
    }

    /**
     * 数据写入的回调
     * @param data
     */
    public void invokeInsert(List<Serializable[]> data){
        invoke(data,listener::onInsert);
    }

    /**
     *
     * @param data
     */
    public void invokeDelete(List<Serializable[]> data){
        invoke(data,listener::onDelete);
    }

    /**
     *
     * @param data
     */
    public void invokeUpdate(List<Map.Entry<Serializable[],Serializable[]>> data){
        data.forEach(o-> listener.onUpdate(toEntity(o.getKey()),toEntity(o.getValue())));
    }


    private void invoke(List<Serializable[]> data, Consumer<T> consumer){
        if(data==null||data.size()==0){
            return;
        }
        data.stream().map(this::toEntity).forEach(consumer);
    }
}
